﻿using Lonewolf.IService;
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.EntityFrameworkCore;
using Lonewolf.Entity;
using System.Linq;
using System.Transactions;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Lonewolf.Service
{
    public partial class BaseService<T> : IBaseService<T> where T : BaseEntity
    {
        private readonly EFDbContext DbContext;
        protected readonly DbSet<T> ts;
        public BaseService(EFDbContext dbContext)
        {
            ts = dbContext.Set<T>();
            DbContext = dbContext;
        }
        /// <summary>
        /// 执行伪删除
        /// </summary>
        /// <param name="entity">实体</param>
        public void DeleteForge(T entity)
        {
            if (entity == null)
                throw new ArgumentNullException(nameof(entity));
            entity.IsDelete = true;
            entity.LastChangeTime = DateTime.Now;
            Update(entity);
        }
        /// <summary>
        /// 执行伪删除
        /// </summary>
        /// <param name="express">条件</param>
        public void DeleteForge(Expression<Func<T, bool>> express)
        {
            var entities = Query().Where(express).ToList();
            if (entities != null && entities.Count > 0)
            {
                entities.ForEach(entity => DeleteForge(entity));
            }
        }
        public void Delete(T entity)
        {
            if (entity == null)
                throw new ArgumentNullException(nameof(entity));
            ts.Remove(entity);
        }
        public void Delete(Expression<Func<T, bool>> express, bool isDelete=false)
        {
            var entities = Query(isDelete).Where(express).ToList();
            if (entities != null && entities.Count > 0)
            {
                entities.ForEach(entity => Delete(entity));
            }
        }
        /// <summary>
        /// 查询对象
        /// </summary>
        /// <param name="isFilter">是否过滤已执行伪删除的数据，默认为true:过滤</param>
        /// <returns></returns>
        public virtual IQueryable<T> Query(bool isFilter = true)
        {
            return isFilter ? ts.AsTracking().Where(p => p.IsDelete == false) : ts.AsTracking();
        }
        /// <summary>
        /// 查询不跟踪实体
        /// </summary>
        /// <param name="isFilter"></param>
        /// <returns></returns>
        public virtual IQueryable<T> QueryNoTracking(bool isFilter = true)
        {
            return isFilter ? ts.AsNoTracking().Where(p => p.IsDelete == false) : ts.AsNoTracking();
        }
        public virtual string Insert(T model)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }
            else
            {
                model.Id = Guid.NewGuid().ToString("N");
                return ts.Add(model).Entity.Id;
            }
        }
        /// <summary>
        /// 异步新增方法
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<string> InsertAsync(T entity)
        {
            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity));
            }
            else
            {
                entity.Id = Guid.NewGuid().ToString("N");
                var model = await ts.AddAsync(entity);
                return model.Entity.Id;
            }
        }
        public void InsertRange(IEnumerable<T> entities)
        {
            if (entities == null || entities.Count() == 0)
                throw new ArgumentNullException(nameof(entities));

            ts.AddRange(entities);
        }

        public void Update(T entity)
        {
            //修改部分列
            // var test = ts.Attach(entity);//这个方法实现修改部分字段，但是要先附加，执行这句以后再给实体赋值要修改的字段
            var model = DbContext.Entry(entity);
            model.State = EntityState.Modified;//Attach
        }
        public void UpdateAttach(T entity)
        {
            ts.Attach(entity);
        }

        public bool SaveChanges()
        {
            return DbContext.SaveChanges() >= 1 ? true : false;
        }
        public async Task<bool> SaveChangesAsync()
        {
            return await DbContext.SaveChangesAsync() >= 1 ? true : false;
        }


    }
}
